﻿/* ######################################## *\
 * ### Copyright (C) 2009 AJ Ravindiran ### *
\* ######################################## */
using System;
using System.Net.Sockets;

using AJRavindiran.Jolt.RuneScape.Models.Characters.Information;
using AJRavindiran.Jolt.RuneScape.Models.Characters.Request;
using AJRavindiran.Jolt.RuneScape.Models.Characters.Update;
using AJRavindiran.Jolt.RuneScape.Network;
using AJRavindiran.Jolt.RuneScape.Network.Streaming;

namespace AJRavindiran.Jolt.RuneScape.Models.Characters
{
    /// <summary>
    /// Represents one character in the game.
    /// </summary>
    public class Character : Entity
    {
        #region Fields
        private StreamReader streamReader;
        private StreamWriter streamWriter;
        private PlayerSocket socket;

        private Details details;
        private Status status;
        private Sprites sprites;
        private Appearance appearance;
        private UpdateFlags updateFlags;
        private Movement movement;
        private ChatMessage lastChatMessage;
        #endregion Fields

        #region Properties
        #endregion Properties

        #region Constructors
        /// <summary>
        /// Constructs a new character for a player.
        /// </summary>
        /// <param name="playerSocket">The player's socket created by the tcp connection.</param>
        /// <param name="connectionID">The player's connection id.</param>
        /// <param name="ipAddress">The player's ip address.</param>
        public Character(Socket playerSocket, int connectionID, string ipAddress)
        {
            // Create a new socket for sending and revieving data.
            this.socket = new PlayerSocket(this, playerSocket);

            // Informative stuff.
            this.details = new Details(connectionID, ipAddress);
            this.status = new Status();
            this.sprites = new Sprites();
            this.appearance = new Appearance();
            this.updateFlags = new UpdateFlags();
            this.movement = new Movement(this);
            
            // Requests stuff
            this.lastChatMessage = null;

            // Create a new stream factory for this user.
            this.streamReader = new StreamReader(512);
            this.streamWriter = new StreamWriter(1024);
        }
        #endregion Constructors

        #region Methods
        /// <summary>
        /// A process called every 600ms.
        /// </summary>
        public void Tick()
        {
        }

        /// <summary>
        /// Destroy the character.
        /// </summary>
        public void Destroy()
        {
            this.GetStatus().Online = false;
            this.socket = null;
        }

        /// <summary>
        /// Appends a graphic effect. Displayed on the next character update.
        /// </summary>
        /// <param name="id">The id of the graphics.</param>
        public override void AppendGraphics(int id)
        {
            this.AppendGraphics(id, 0);
        }

        /// <summary>
        /// Appends a graphic effect. Displayed on the next character update.
        /// </summary>
        /// <param name="id">The id of the graphics.</param>
        /// <param name="delay">Delay ammount of the graphics.</param>
        public override void AppendGraphics(int id, int delay)
        {
            this.SetLastGraphics(new Graphics(id, delay));
            this.updateFlags.GraphicsUpdateRequired = true;
        }

        /// <summary>
        /// Appends a animation. Displayed on the next character update.
        /// </summary>
        /// <param name="id">The if of the animation.</param>
        public override void AppendAnimation(int id)
        {
            this.AppendAnimation(id, 0);
        }

        /// <summary>
        /// Appends a animation. Displayed on the next character update.
        /// </summary>
        /// <param name="id">The if of the animation.</param>
        /// <param name="delay">Delay ammount of the animation.</param>
        public override void AppendAnimation(int id, int delay)
        {
            this.SetLastAnimation(new Animation(id, delay));
            this.updateFlags.AnimationUpdateRequired = true;
        }

        /// <summary>
        /// Accessor for the player's socket.
        /// </summary>
        public PlayerSocket GetSocket()
        {
            return this.socket;
        }

        /// <summary>
        /// Accessor for the player's stream reader.
        /// </summary>
        public StreamReader GetStreamReader()
        {
            return this.streamReader;
        }

        /// <summary>
        /// Accessor for the player's stream writer.
        /// </summary>
        public StreamWriter GetStreamWriter()
        {
            return this.streamWriter;
        }

        /// <summary>
        /// Accessor for the character's details.
        /// </summary>
        public Details GetDetails()
        {
            return this.details;
        }

        /// <summary>
        /// Accessor for the character's status.
        /// </summary>
        public Status GetStatus()
        {
            return this.status;
        }

        /// <summary>
        /// Accessor for the character's client sprite.
        /// </summary>
        public Sprites GetSprites()
        {
            return this.sprites;
        }

        /// <summary>
        /// Accessor for the character's appearance.
        /// </summary>
        public Appearance GetAppearance()
        {
            return this.appearance;
        }

        /// <summary>
        /// Accessor for the character's update flags.
        /// </summary>
        public UpdateFlags GetUpdateFlags()
        {
            return this.updateFlags;
        }

        /// <summary>
        /// Accessor for the character's movement.
        /// </summary>
        public Movement GetMovement()
        {
            return this.movement;
        }

        /// <summary>
        /// Accessor for the character's last chat message.
        /// </summary>
        public ChatMessage GetLastChatMessage()
        {
            return this.lastChatMessage;
        }
        #endregion Methods
    }
}
